// 指针运算：1 + 1 = 2？

#include <stdio.h>

int main(int argc, char const *argv[])
{
    char ac[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1};
    char* p = ac;
    printf("p\t = %p\n", p);
    // p = 000000000061FE0E
    printf("p + 1\t = %p\n", p + 1);
    // p + 1 = 000000000061FE0F -> p + sizeof(char)
    printf("\n*p\t = %d\n", *p);
    // *p -> ac[0]
    // * 运算优先级高于 + ，所以要加括号
    printf("*(p + 1) = %d\n", *(p + 1));
    // *(p + 1) -> ac[1]
    // *(p + n) -> ac[n]

    int ai[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,};
    int *q = ai;
    printf("\nq\t = %p\n", q);
    // q = 000000000061FDD0
    printf("q + 1\t = %p\n", q + 1);
    // q + 1 = 000000000061FDD4 -> q + sizeof(int)

    // 指针可以做加减运算
    // 也可以用 ++/-- 运算
    // 还可以两个指针相加减
    char* p1 = &ac[5];
    printf("\n*(p1 - 3)= %d\n", *(p1 - 3));
    // *(p1 - 3) = 2 -> ac[2]
    printf("p1 - p\t = %d\n", p1 - p);
    // p1 - p = 5
    // p1 - p -> (p1 - p) / sizeof(char)

    char test[] = {1, 2, 3, 4, 5,};
    char* p2 = test;
    printf("%d\n", p1 - p2);
    // 测试发现，不同类型的指针不能相减
    // 相同类型的指针相减，值为地址之差除以数据类型大小 -> (p1 - p2) / sizeof(char)

    // *p++
    // ++ 优先级高于 * ，而 p++ 的值还是 p
    // 把 p 所指的数据取出，完事把 p 移到下一个位置
    // 常用于数组类的连续空间操作
    // 在某些CPU上,这个可以被翻译成一条汇编指令
    // 可以用于遍历
    printf("\n");
    while (*p != -1)
    {
        printf("%d", *p++);
    }
    printf("\n");

    // 指针比较
    // 大于/小于/等于 -> (地址)

    // 0地址
    // 虚拟地址从0开始
    // 指针不应该指向0
    // 可以用0地址表示特殊的事情
    //      返回的指针是无效的
    //      指针没有被真正初始化(先初始化为0)
    // NULL是一个预定义的符号, 表示0地址
    //      有点编译器不愿意我用0表示0地址, 所以用 NULL 更好一点

    // 不同类型的指针大小相同, 因为都是地址值
    // 但是指向不同类型的指针不能互相赋值 -> 避免用错

    // 指针类型转换
    // void* : 表示不知道指向啥玩意的指针
    //      计算时与 char* 相同, 但不相通
    // 指针也可以转换类型
    int i;
    int* pointer = &i;
    *pointer = 1;
    printf("\n%d\n", i);
    // 不会改变 pointer 所指的变量类型, 只是用不同眼光通过 pointer 看它所指向的变量
    // 通过 pointer 看 i , 看到 int
    // 通过 qointer 看 i , 看到 void
    void* qointer = (void*)pointer;
    // 以上过程没有改变pointer的类型
    *pointer = 0xFFFF;
    printf("%d\n", i);

    // warning: dereferencing 'void *' pointer
    // error: invalid use of void expression
    // 不能用 void* 指针对变量赋值
    // *qointer = 3;
    // 也不能读取其指向变量的值
    // printf("%d\n", *qointer);

    return 0;
}